package com.rzx.mybackend.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rzx.mybackend.annotation.CommentIdempotent;
import com.rzx.mybackend.config.websocket.WebSocketEndpoint;
import com.rzx.mybackend.entity.GameComment;
import com.rzx.mybackend.entity.RabbitMQLog;
import com.rzx.mybackend.entity.User;
import com.rzx.mybackend.mapper.CommentMapper;
import com.rzx.mybackend.service.CommentService;
import com.rzx.mybackend.service.RabbitMQService;
import com.rzx.mybackend.service.UserService;
import com.rzx.mybackend.vo.CommentVO;
import com.rzx.mybackend.vo.GameCommentVO;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

/**
 * CommentServiceImpl
 *
 * @author renzhexian
 * @date 2025/7/22
 */
@Service
@RequiredArgsConstructor
public class CommentServiceImpl implements CommentService {

    private final CommentMapper commentMapper;
    @Value("${spring.rabbitmq.comment.exchange_name}")
    private String COMMENT_EXCHANGE_NAME;
    @Value("${spring.rabbitmq.comment.routing_key}")
    private String COMMENT_ROUTING_KEY;
    @Value("${spring.rabbitmq.comment.queue_name}")
    private String COMMENT_QUEUE_NAME;

    private static final Logger log = LoggerFactory.getLogger(CommentServiceImpl.class);

    private final RabbitTemplate rabbitTemplate;

    private final UserService userService;

    private final RabbitMQService rabbitMQService;

    private final ObjectMapper objectMapper;

    /*
    用户发布评论（并进行幂等校验）
     */
    @CommentIdempotent
    @Override
    public void putComment(GameComment gameComment) {

        // TODO: 此处以后使用Redis缓存用户信息，减少数据库查询

        User user = userService.selectAllByUserId(gameComment.getUserId());

        // RabbitMQ消息落库
        String uuid = UUID.randomUUID().toString();

        String msgString = null;

        try {
            msgString = objectMapper.writeValueAsString(gameComment);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("序列化失败"+e);
        }

        rabbitMQService.logComment(RabbitMQLog.builder()
                .msgId(uuid)
                .mqExchange(COMMENT_EXCHANGE_NAME)
                .mqRoute(COMMENT_ROUTING_KEY)
                .mqQueue(COMMENT_QUEUE_NAME)
                .msgContent(msgString)
                .logTime(new java.util.Date())
                .build());

        log.info("用户{}发布评论，并用消息队列处理写入数据库",user.getUserName());

        // RabbitMQ发送异步消息，存储评论到数据库
        rabbitTemplate.convertAndSend(COMMENT_EXCHANGE_NAME, COMMENT_ROUTING_KEY, gameComment,new CorrelationData(uuid));

        // 异步发送，避免阻塞和异常传播
//        CompletableFuture.runAsync(() -> {
//            try {
//                rabbitTemplate.convertAndSend(COMMENT_EXCHANGE_NAME, COMMENT_ROUTING_KEY, gameComment, new CorrelationData(uuid));
//            } catch (Exception e) {
//                log.error("异步发送消息失败", e);
//            }
//        });

        log.info("开始执行WebSocket推送评论");

        // WebSocket实时推送评论
        WebSocketEndpoint.pushToAll(GameCommentVO.builder()
                .gameId(gameComment.getGameId())
                .commentContent(gameComment.getCommentContent())
                .commentTime(gameComment.getCommentTime())
                .nickName(user.getNickName())
                .avatar(user.getAvatar())
                .build());

    }

    /*
    根据游戏ID获取游戏评论
     */
    @Override
    public List<CommentVO> getComment(Long gameId) {

        List<GameComment> gameCommentList  = commentMapper.getCommentsByGameId(gameId);

        if (gameCommentList == null || gameCommentList.isEmpty()) {
            return List.of(); // 返回空列表而不是null
        }

        return gameCommentList.stream().map(
                gameComment -> CommentVO.builder()
                        .nickName(userService.selectAllByUserId(gameComment.getUserId()).getNickName())
                        .commentContent(gameComment.getCommentContent())
                        .commentTime(gameComment.getCommentTime())
                        .build()
        ).toList();
    }
}
